package com.zynn.service.module.calculate.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.zynn.common.core.constant.RecommendConstant;
import com.zynn.common.core.utils.SequenceUtil;
import com.zynn.common.core.utils.TypeConvertUtil;
import com.zynn.common.pojo.dto.user.UserDataDTO;
import com.zynn.message.queue.constant.MqQueueNameConstant;
import com.zynn.service.module.calculate.bo.DegOneFrientWithWeight;
import com.zynn.service.module.calculate.constant.ESTableConstant;
import com.zynn.service.module.calculate.dao.BlendBaseUserCacheMapper;
import com.zynn.service.module.calculate.entity.Events;
import com.zynn.service.module.calculate.service.EventsService;
import com.zynn.service.module.calculate.service.InitVersionV3FriendsService;
import com.zynn.service.module.calculate.util.RecommandUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisCluster;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jerry-liqi
 *
 * 计算推荐好友信息
 *
 */
@Slf4j
@Service
public class InitVersionV3FriendsServiceImpl implements InitVersionV3FriendsService {

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    BlendBaseUserCacheMapper blendBaseUserCacheMapper;

    @Autowired
    EventsService eventsService;

    @Autowired
    private JedisCluster jedisCluster;

    /**
     * 权重分数
     */
    private static final int DEG_ONE_WEIGHT_SCORE = 20;
    private static final int DEG_TWO_WEIGHT_SCORE = 10;
    private static final int DEG_THREE_WEIGHT_SCORE = 5;

    private static final int CALC_TYPE_01 = 1;
    private static final int CALC_TYPE_02 = 2;


    private static final int DEG_ONE = 1;
    private static final int DEG_TWO = 2;

    /** 1. 同校邀请关系的权重分数 暂定同校好友 具有邀请操作的 +100分*/
    private static final int SCHOOL_INVITE_WEIGHT_SCORE = 1600;

    /** 2. 关注我的 且我未关注的 分值*/
    private static final int USER_BE_ATTENTION_WEIGHT_SCORE = 800;

    /** 3. 我关注的 且还未关注我的 分值*/
    private static final int MY_ATTENTION_WEIGHT_SCORE = 300;

    /** 4. 互相关注的 分值 */
    private static final int USER_ATTENTION_EACH_OTHER_WEIGHT_SCORE = 100;

    /** 5. 同城同区域用户关系 权重分数 */
    private static final int SAME_CITY_AND_AREA_WEIGHT_SCORE = 1;

    /** 同城不同区域用户关系，权重分数 */
    private static final int SAME_CITY_WEIGHT_SCORE = 1;




    /** 1,没有填写学校资料*/
    private int PROFILE_TYPE_0 = 0;

    /** 2.标识有学校信息 */
    private int PROFILE_TYPE_1 = 1;

    /** 没有填写城市资料 */
    private int PROFILE_CITY_TYPE_0 = 0;

    /** 填写了学校资料 */
    private int PROFILE_CITY_TYPE_1 = 1;

    @JmsListener(destination = MqQueueNameConstant.FIND_FRIEND_FORM_USER_FRIEND)
    public void findFriendM1(Map<String, Object> columnsMap) {
        log.info("FIND_FRIEND_FORM_USER_FRIEND:{}", columnsMap);
        Long inviteUserId = TypeConvertUtil.objectToLong(columnsMap.get("invite_user_id"));
        if (inviteUserId != null && inviteUserId != 0) {
            this.initFriendV3(inviteUserId);
        }
        Long acceptUserId = TypeConvertUtil.objectToLong(columnsMap.get("accept_user_id"));
        if (Objects.nonNull(acceptUserId)) {
            this.initFriendV3(acceptUserId);
        }
    }

    @JmsListener(destination = MqQueueNameConstant.FIND_FRIEND_FORM_LIKE)
    public void findFriendM2(Map<String, Object> columnsMap) {
        Long likeEventID = TypeConvertUtil.objectToLong(columnsMap.get("likeEventID"));
        if (Objects.nonNull(likeEventID)) {
            Events event = eventsService.selectOne(new EntityWrapper<Events>().eq("eid", likeEventID));
            if (Objects.nonNull(event)) {
                Long euserId = Long.valueOf(event.getEuserid());
                if (Objects.nonNull(euserId)) {
                    this.initFriendV3(euserId);
                }
            }
        }
        Long likeUserID = TypeConvertUtil.objectToLong(columnsMap.get("likeUserID"));
        if (Objects.nonNull(likeUserID)) {
            this.initFriendV3(likeUserID);
        }
    }

    @JmsListener(destination = MqQueueNameConstant.FIND_FRIEND_FORM_BASE_USER_INFO)
    public void findFriendM3(Map<String, Object> columnsMap) {
        Long userId = TypeConvertUtil.objectToLong(columnsMap.get("user_id"));
        this.initFriendV3(userId);
    }

    @JmsListener(destination = MqQueueNameConstant.FIND_FRIEND_FORM_REMINDUSER)
    public void findFriendM4(Map<String, Object> columnsMap) {
        /**
         * 被@的用户id
         */
        Long remindUserId = TypeConvertUtil.objectToLong(columnsMap.get("remindUserId"));
        if (Objects.nonNull(remindUserId)) {
            this.initFriendV3(remindUserId);
        }
        /**
         * 主动@用户id
         */
        Long userId = TypeConvertUtil.objectToLong(columnsMap.get("userId"));
        if (Objects.nonNull(userId)) {
            this.initFriendV3(userId);
        }
    }

    @JmsListener(destination = MqQueueNameConstant.FIND_FRIEND_FORM_COMMENTS)
    public void findFriendM5(Map<String, Object> columnsMap) {
        /**
         * 被评论者id
         */
        Long ceduserid = TypeConvertUtil.objectToLong(columnsMap.get("ceduserid"));
        if (Objects.nonNull(ceduserid)) {
            if(Objects.equals(10L,ceduserid)){
                /**评论动态**/
                    /**被评论者**/
                Long ceid = TypeConvertUtil.objectToLong(columnsMap.get("ceid"));
                Events event = eventsService.selectOne(new EntityWrapper<Events>().eq("eid", ceid));
                if (Objects.nonNull(event)) {
                    this.initFriendV3(Long.valueOf(event.getEuserid()));
                }
                /**评论者**/
                this.initFriendV3(TypeConvertUtil.objectToLong(columnsMap.get("cuserid")));
            }else{
                /**回复评论**/
                    /**被评论者**/
                this.initFriendV3(ceduserid);
                    /**评论者**/
                this.initFriendV3(TypeConvertUtil.objectToLong(columnsMap.get("cuserid")));
            }

        }
    }


    /**
     * 监控关注表
     *
     * @author jerry-liqi
     *
     * @param columnsMap 表字段
     */
    @JmsListener(destination = MqQueueNameConstant.FIND_FIEND_FROM_ATTENTION_RELATION)
    public void findFriendAttentionRelation(Map<String, Object> columnsMap) {

        /** 主动关注的用户 */
        Long attention_user_id = TypeConvertUtil.objectToLong(columnsMap.get("attention_user_id"));
        if (Objects.nonNull(attention_user_id)) {
            this.initFriendV3(attention_user_id);
        }

        /** 被关注的用户 */
        Long be_attention_user_id = TypeConvertUtil.objectToLong(columnsMap.get("be_attention_user_id"));
        if (Objects.nonNull(be_attention_user_id)) {
            this.initFriendV3(be_attention_user_id);
        }
    }


    /**
     * @author 刘猛
     * @author jerry-liqi
     *
     * 1. 一度算法推荐好友
     * 2. 同校好友推荐列表
     *
     * @param userId 被推荐用户ID
     */
    @Override
    public void initFriendV3(Long userId) {

        /** 查询 v3, v4算法返回结果*/
        Map<String,Object> result = this.queryUserRecommendWithWeightDegAll(userId);


        if (Objects.nonNull(result.get("v3"))) {
            // v3算法 结果集合
            List<DegOneFrientWithWeight> recommendListDegAll = (List<DegOneFrientWithWeight>)result.get("v3");
            // 一度算法存储 ES
            if (CollectionUtils.isNotEmpty(recommendListDegAll)) {
                List<String> friendsWithWeight = recommendListDegAll.stream().map((e) -> e.getWeight() + "|" + e.getUserId()).collect(Collectors.toList());
                this.syncDegAllFriends(userId, friendsWithWeight);
            }
        }

        /** v4算法 结果集合(同校好友推荐列表) */
        if (Objects.nonNull(result.get("v4"))) {
            List<DegOneFrientWithWeight> v4All = (List<DegOneFrientWithWeight>)result.get("v4");
            List<String> friendsWithWeight = v4All.stream().map((e) ->JSON.toJSONString(e)).collect(Collectors.toList());
            this.syncSchoolFriends(userId,friendsWithWeight);
        }

        try {
            /** 推荐好友变化时，清除推荐好友redis缓存 */
            jedisCluster.del(RecommendConstant.RECOMMAND_SAME_SCHOOL_FRIEND_REDIS_KEY_PREFIX + userId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将推荐好友信息同步到es
     * 同步好友信息 到ES
     */
    private void syncDegAllFriends(Long userId, List<String> friendWithWeight) {
        if (RecommandUtil.existsIndex(userId, client)) {
            // 修改ES 推荐的好友列表
            this.updateBlendIndex(userId, friendWithWeight);
        } else {
            // 新建ES 推荐好友列表
            this.createBlendIndex(userId, friendWithWeight);
        }
    }

    /**
     * @author 李琦
     * @param userId 被推荐用户ID
     * @param schoolFriendWithWeight 同校好友推荐列表
     *
     */
    private void syncSchoolFriends(Long userId,List<String> schoolFriendWithWeight){
        ESTableConstant esTableConstant = new ESTableConstant(ESTableConstant.V4_ES_INDEX,ESTableConstant.V4_ES_TYPE);
        Map<String, Object> jsonMap = new HashMap<>(20);
        jsonMap.put(ESTableConstant.V4_ES_SOURCE_KEY, schoolFriendWithWeight);
        jsonMap.put("user_id", userId);
        if (RecommandUtil.existsIndex(userId, client)) {
            // 修改ES 推荐的好友列表
            this.updateEsInfo(jsonMap,userId,esTableConstant);
        } else {
            // 新建ES 推荐好友列表
            this.createEsInfo(jsonMap,userId, esTableConstant);
        }
    }

    /**
     * @author jerry-liqi
     *
     * 备注: 修改Es缓存内容
     *
     */
    private void updateEsInfo(Map<String,Object> jsonMap, Long userId, ESTableConstant esTableConstant){
        //Map会自动转换为JSON格式的文档源
        UpdateRequest indexRequest = new UpdateRequest(esTableConstant.getIndexName(), esTableConstant.getType(), userId.toString())
                .doc(jsonMap);
        UpdateResponse indexResponse = null;
        try {
            indexResponse = client.update(indexRequest);
            log.info(indexResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author jerry-liqi
     *
     * 备注: 新建ES缓存内容
     */
    private void createEsInfo(Map<String,Object> jsonMap, Long userId, ESTableConstant esTableConstant){
        //Map会自动转换为JSON格式的文档源
        IndexRequest indexRequest = new IndexRequest(esTableConstant.getIndexName(), esTableConstant.getType(), userId.toString())
                .source(jsonMap);
        IndexResponse indexResponse = null;
        try {
            indexResponse = client.index(indexRequest);
            log.info(indexResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * v3版推荐索引（更新）
     *
     * @param userId 被推荐用户ID
     * @param friendWithWeight 推荐好友
     */
    private void updateBlendIndex(Long userId, List<String> friendWithWeight) {
        Map<String, Object> jsonMap = new HashMap<>(20);
        jsonMap.put("blend_user_friend_with_weight", friendWithWeight);

        //Map会自动转换为JSON格式的文档源
        UpdateRequest indexRequest = new UpdateRequest("user_friend_index", "_doc", userId.toString())
                .doc(jsonMap);
        UpdateResponse indexResponse = null;
        try {
            indexResponse = client.update(indexRequest);
            log.info(indexResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * v3版推荐索引（创建）
     *
     * @param userId
     * @param friendWithWeight
     */
    private void createBlendIndex(Long userId, List<String> friendWithWeight) {
        Map<String, Object> jsonMap = new HashMap<>(20);
        jsonMap.put("user_id", userId);
        jsonMap.put("blend_user_friend_with_weight", friendWithWeight);

        //Map会自动转换为JSON格式的文档源
        IndexRequest indexRequest = new IndexRequest("user_friend_index", "_doc", userId.toString())
                .source(jsonMap);
        IndexResponse indexResponse = null;
        try {
            indexResponse = client.index(indexRequest);
            log.info(indexResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * @author 刘猛 and jerry-liqi
     *
     * @param userId 被推荐用户ID
     *
     * @return Map<String,Object> map
     */
    public Map<String,Object> queryUserRecommendWithWeightDegAll(Long userId) {

        Map<String,Object> result = new HashMap<>(30);

        Long sequenceDegOne = SequenceUtil.getId();
        Long sequenceDegTwo = SequenceUtil.getId();
        Long sequenceDegThree = SequenceUtil.getId();

        // 是否填写学校资料
        int type = this.getSchoolInfoFillRatio(userId);

        /** 判断用户是否填写省份和城市资料 */
        int haveCity = 0;
///        Set<Long> uId = blendBaseUserCacheMapper.getUserIdCityAndAreaIsnull(userId);
//        if (uId.size() > 0 ){
//            haveCity = 1;
//        }


        try {
            /** 1. 插入缓存数据 */
            blendBaseUserCacheMapper.insertBlendBaseRecommendUsers2CacheTableDegOne(sequenceDegOne, userId);

            /** 2. 计算推荐好友 */
            result = this.getDegFriends(userId, type,haveCity,sequenceDegOne, DEG_ONE_WEIGHT_SCORE, null);


           /* if (CollectionUtils.isNotEmpty(recommendFriendsDegOne)) {
                recommendFriendsAll.addAll(recommendFriendsDegOne);
            }*/


            /// 计算二度好友 暂时停用
            // blendBaseUserCacheMapper.insertBlendBaseRecommendUsers2CacheTable(userId,sequenceDegTwo,sequenceDegOne);
            // List<DegOneFrientWithWeight> recommendFriendsDegTwo = this.getDegFriends(userId,type,sequenceDegTwo,DEG_TWO_WEIGHT_SCORE,sequenceDegOne);
            // if(CollectionUtils.isNotEmpty(recommendFriendsDegTwo)){
            //     recommendFriendsAll.addAll(recommendFriendsDegTwo);
            // }

            /// 计算三度好友 目前暂时停用
            // blendBaseUserCacheMapper.insertBlendBaseRecommendUsers2CacheTable(userId,sequenceDegThree,sequenceDegTwo);
            // List<DegOneFrientWithWeight> recommendFriendsDegThree = this.getDegFriends(userId,type,sequenceDegThree,DEG_THREE_WEIGHT_SCORE,sequenceDegTwo);
            // if(CollectionUtils.isNotEmpty(recommendFriendsDegThree)){
            //     recommendFriendsAll.addAll(recommendFriendsDegThree);
            // }

            //if (CollectionUtils.isNotEmpty(recommendFriendsAll)) {
            // 排除自己
            //RecommandUtil.removeMyself(recommendFriendsAll, userId);
            // 推荐用户重复时，选择分数高者
            //RecommandUtil.getHightestScoreRecommendUser(recommendFriendsAll);
            //}
            //

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            blendBaseUserCacheMapper.deleteCacheDatas(Arrays.asList(sequenceDegOne, sequenceDegTwo, sequenceDegThree));

        }
        return result;
    }

    /**
     * @author 猛哥,jerry-liqi
     *
     * 查询用户好友
     * @param type 是否填写 学校资料
     * @param sequenceDeg    本度用户
     * @param score 默认分数20,10
     * @return Map<String,Object>
     */
    private Map<String,Object> getDegFriends(Long userId, int type,int haveCity, Long sequenceDeg, int score, Long sequenceDegUp) {
        List<DegOneFrientWithWeight> resultSchool = Lists.newLinkedList();
        List<DegOneFrientWithWeight> resultHandle;
        Map<String,Object> resultMap = new HashMap<>(30);

        /**  1. 有学校信息 就要查询学校权重用户 */
        if (type == PROFILE_TYPE_1) {
            resultSchool = querySchoolWeightFriends(userId, sequenceDeg, score);
        }
        resultHandle = queryHandleWeightFriends(userId, sequenceDeg, sequenceDegUp);

        /** 2. 汇总 高校推荐好友和操作推荐好友 */
        List<DegOneFrientWithWeight> result = this.mergeFriendsScore(resultSchool, resultHandle);


        /**
         * 3.判断用户是否填写省份和城市 如果同省同城,该用户+1分
         */
        if (haveCity == PROFILE_CITY_TYPE_1 && CollectionUtils.isNotEmpty(result)) {
            result = this.caculateSameCityScore(result,userId);
        }


        if (CollectionUtils.isNotEmpty(result)) {
            /** 排除自己 */
            RecommandUtil.removeMyself(result, userId);
            /** 推荐用户重复时，选择分数高者 */
            RecommandUtil.getHightestScoreRecommendUser(result);
            resultMap.put("v3",result);
        }


        if (CollectionUtils.isNotEmpty(resultSchool)){

            /** 4. 返回同校好友推荐+我已经关注的推荐好友  （带有学校，学院，年级，性别） */
            List<DegOneFrientWithWeight> v4SchoolFriends = this.returnSchoolFriends(userId,resultSchool,resultHandle);


            /** 5. 同省同城+1分 */
            if (haveCity == PROFILE_CITY_TYPE_1 && CollectionUtils.isNotEmpty(v4SchoolFriends)) {
                v4SchoolFriends = this.caculateSameCityScore(v4SchoolFriends,userId);
            }

            if (CollectionUtils.isNotEmpty(v4SchoolFriends)) {
                resultMap.put("v4",v4SchoolFriends);
            }
        }

        return resultMap;
    }

    /**
     * 1.同省同城好友算法计算
     *
     * 2.同省不同城算法计算
     *
     * @return
     */
    private List<DegOneFrientWithWeight> caculateSameCityScore(List<DegOneFrientWithWeight> result,Long userId){

        Set<Long> set = result.stream().map(DegOneFrientWithWeight::getUserId).collect(Collectors.toSet());
        String ids = StringUtils.join(set,",");

        /** 同省同城好友+1分 */
        Set<Long> inSameProvinceAndCity = this.getUserIdHaveSameProvinceAndCity(userId,ids);
        if (CollectionUtils.isNotEmpty(inSameProvinceAndCity)) {
            result.stream().filter(tmp -> inSameProvinceAndCity.contains(tmp.getUserId())).forEach(
                    tmp -> tmp.setWeight(tmp.getWeight() + SAME_CITY_AND_AREA_WEIGHT_SCORE)
            );
        }

///
//        Set<Long> inSameProvinceDiffCity = blendBaseUserCacheMapper.getUserIdHaveSameProvinceWithDiffCity(userId);
//        if (CollectionUtils.isNotEmpty(inSameProvinceDiffCity)) {
//            for (DegOneFrientWithWeight tmp : result) {
//                if (inSameProvinceDiffCity.contains(tmp.getUserId())) {
//                    tmp.setWeight(tmp.getWeight()+SAME_CITY_WEIGHT_SCORE);
//                }
//            }
//        }
        return result;
    }


    /**
     * @author jerry-liqi
     *
     * 获取用户同省同城好友
     * @param userId
     * @return
     */
    private Set<Long> getUserIdHaveSameProvinceAndCity(Long userId,String ids){
        return blendBaseUserCacheMapper.getUserIdHaveSameProvinceAndCity(userId,ids);
    }


    /**
     * @author 李琦
     *
     * 备注：返回同校推荐好友 (带有学校资料，学校ID,学院ID,年级ID)
     *
     * @return List<DegOneFrientWithWeight>
     */
    private List<DegOneFrientWithWeight> returnSchoolFriends(Long userId,List<DegOneFrientWithWeight> resultSchool,List<DegOneFrientWithWeight> resultHandle){

        // 没有学校资料的同校好友集合
        List<DegOneFrientWithWeight> recommendAll = Lists.newLinkedList();

        /** 1. 查找我已经关注的 同校好友 */
        List<DegOneFrientWithWeight> myAttentionSchoolFriends = this.getMyAttentionFriends(userId);
        recommendAll.addAll(myAttentionSchoolFriends);

        /** 2. 筛选出只是同校好友的用户 */
        if (CollectionUtils.isNotEmpty(resultSchool)) {

            if (CollectionUtils.isNotEmpty(resultHandle)) {
                Map<Long, DegOneFrientWithWeight> handleFriendsMap = resultHandle.stream().collect(Collectors.toMap(DegOneFrientWithWeight::getUserId, e -> e));
                DegOneFrientWithWeight handleFriend;
                for (DegOneFrientWithWeight tmp : resultSchool) {
                    handleFriend = handleFriendsMap.get(tmp.getUserId());
                    if (Objects.nonNull(handleFriend)) {
                        /** 同校好友的最终分值 */
                        tmp.setWeight(tmp.getWeight()+handleFriend.getWeight());
                    }
                }
            }
            recommendAll.addAll(resultSchool);
        }

        /** 1.排除自己账号。推荐重复时 选择分数高的用户*/
        RecommandUtil.removeMyself(recommendAll, userId);
        RecommandUtil.getHightestScoreRecommendUser(recommendAll);

        // 2.邀请关系的权重分
        recommendAll = this.calculateInvitation(userId,recommendAll);

        // 3 关注我的 且我未关注的
        recommendAll = this.calculateHaveAttentionUser(userId,recommendAll);

        // 4 我关注的 没有关注我的
        recommendAll = this.calculateUserHaveAttention(userId,recommendAll);

        // 5 互相关注的用户
        recommendAll = this.calculateUserAttentionEachOther(userId,recommendAll);


        List<DegOneFrientWithWeight> result = Lists.newLinkedList();
        if (CollectionUtils.isNotEmpty(recommendAll)) {
            /** 拿出所有用户ID。去查询他们的:学校ID 学院ID,年级ID,性别 */
            Set<Long> set = recommendAll.stream().map(DegOneFrientWithWeight::getUserId).collect(Collectors.toSet());
            String ids = StringUtils.join(set,",");
            List<DegOneFrientWithWeight> tmpSchoolFriends = this.getRecommendFriendsWithElseInfo(ids);

            /** 最终的合并 */
            result = this.mergeSchoolFriendsWithWeight(tmpSchoolFriends,recommendAll);
        }

        return result;
    }

    /**
     * @author jerry-liqi
     *
     * 备注：计算邀请关系的
     *
     * @return list
     */
    private List<DegOneFrientWithWeight> calculateInvitation(Long userId,List<DegOneFrientWithWeight> recommendAll){
        Set<Long> userIdWithInvitation = this.getSchoolUserIdWithInvitation(userId);
        if (CollectionUtils.isNotEmpty(userIdWithInvitation)) {
            // 判断如果用户具有邀请关系 +邀请分值
            recommendAll.stream().filter(tmp -> userIdWithInvitation.contains(tmp.getUserId())).forEach(
                    tmp -> tmp.setWeight(tmp.getWeight() + SCHOOL_INVITE_WEIGHT_SCORE)
            );
        }
        return recommendAll;
    }

    /**
     * @author jerry-liqi
     *
     * 计算关注我的 且我没有关注的用户分值
     *
     * @return List
     */
    private List<DegOneFrientWithWeight> calculateHaveAttentionUser(Long userId,List<DegOneFrientWithWeight> recommendAll){
        Set<Long> haveAttentionMeSet = blendBaseUserCacheMapper.getFriendHaveAttentionMe(userId);
        if (CollectionUtils.isNotEmpty(haveAttentionMeSet)) {
            recommendAll.stream().filter(tmp -> haveAttentionMeSet.contains(tmp.getUserId())).forEach(
                    tmp -> tmp.setWeight(tmp.getWeight() + USER_BE_ATTENTION_WEIGHT_SCORE)
            );
        }
        return recommendAll;
    }

    /**
     * @author jerry-liqi
     *
     * 我关注的用户 且没有关注我的用户分值
     *
     * @return list
     */
    private List<DegOneFrientWithWeight> calculateUserHaveAttention(Long userId,List<DegOneFrientWithWeight> recommendAll){
        Set<Long> myAttentionSet = blendBaseUserCacheMapper.getMyAttentionFriend(userId);
        if (CollectionUtils.isNotEmpty(myAttentionSet)) {
            recommendAll.stream().filter(tmp -> myAttentionSet.contains(tmp.getUserId())).forEach(
                    tmp -> tmp.setWeight(tmp.getWeight() + MY_ATTENTION_WEIGHT_SCORE)
            );
        }
        return recommendAll;
    }



    /**
     * @author jerry-liqi
     *
     * 计算互相关注分值
     *
     * @return list
     */
    private List<DegOneFrientWithWeight> calculateUserAttentionEachOther(Long userId,List<DegOneFrientWithWeight> recommendAll){
        Set<Long> eachOtherSet = blendBaseUserCacheMapper.getAttentionEachOther(userId);
        if (CollectionUtils.isNotEmpty(eachOtherSet)) {
            recommendAll.stream().filter(tmp -> eachOtherSet.contains(tmp.getUserId())).forEach(
                    tmp -> tmp.setWeight(tmp.getWeight() + USER_ATTENTION_EACH_OTHER_WEIGHT_SCORE)
            );
        }
        return recommendAll;
    }



    /**
     * @author jerry-liqi
     * @param userId 被推荐人用户ID
     * @return Set<Long>
     */
    private Set<Long> getSchoolUserIdWithInvitation(Long userId){
        return blendBaseUserCacheMapper.getSchoolUserIdWithInvitation(userId);
    }

    /**
     * @author jerry-liqi
     *
     * 合并两个集合 返回最终结果(同校好友推荐集合)
     *
     * @return List<DegOneFrientWithWeight>
     */
    private List<DegOneFrientWithWeight> mergeSchoolFriendsWithWeight(List<DegOneFrientWithWeight> tmpSchoolFriends,List<DegOneFrientWithWeight> recommendAll) {
        if (CollectionUtils.isEmpty(tmpSchoolFriends)) {
            return tmpSchoolFriends;
        }
        if (CollectionUtils.isEmpty(recommendAll)) {
            return null;
        }

        // 返回最终带有 学校资料的 同校推荐列表
        List<DegOneFrientWithWeight> result = Lists.newLinkedList();
        if (CollectionUtils.isNotEmpty(tmpSchoolFriends) && CollectionUtils.isNotEmpty(recommendAll)) {

            Map<Long, DegOneFrientWithWeight> weightMap = recommendAll.stream().collect(Collectors.toMap(DegOneFrientWithWeight::getUserId, e -> e));
            DegOneFrientWithWeight schFriendWithWight;
            for(DegOneFrientWithWeight sch : tmpSchoolFriends) {
                schFriendWithWight = weightMap.get(sch.getUserId());
                if (Objects.nonNull(schFriendWithWight)){
                    // 存入分值
                    sch.setWeight(schFriendWithWight.getWeight());
                }
            }
            result.addAll(tmpSchoolFriends);
        }
        return result;
    }

    /**
     * @author jerry-liqi
     *
     * 备注: 查找同校 我已经关注的好友
     *
     * @return DegOneFrientWithWeight
     */
    private List<DegOneFrientWithWeight> getMyAttentionFriends(Long userId) {
        return blendBaseUserCacheMapper.getMyAttentionSchoolFriends(userId);
    }



    /**
     * @author jerry-liqi
     *
     * 备注： 获取推荐好友带有辅助资料（学校ID,学院ID,年级ID）
     */
    private List<DegOneFrientWithWeight> getRecommendFriendsWithElseInfo(String ids) {
        return blendBaseUserCacheMapper.getSchoolFriendsWithElseInfo(ids);
    }



    /**
     * 将学校信息推荐用户与操作推荐用户分数汇总
     */
    private List<DegOneFrientWithWeight> mergeFriendsScore(List<DegOneFrientWithWeight> resultSchool, List<DegOneFrientWithWeight> resultHandle) {
        if (CollectionUtils.isEmpty(resultSchool)) {
            return resultHandle;
        }
        if (CollectionUtils.isEmpty(resultHandle)) {
            return resultSchool;
        }
        List<DegOneFrientWithWeight> recommendAll = Lists.newLinkedList();
        if (CollectionUtils.isNotEmpty(resultSchool) && CollectionUtils.isNotEmpty(resultHandle)) {
            Map<Long, DegOneFrientWithWeight> handleFriendsMap = resultHandle.stream().collect(Collectors.toMap(DegOneFrientWithWeight::getUserId, e -> e));
            DegOneFrientWithWeight handleFriend;
            for (DegOneFrientWithWeight friend : resultSchool) {
                handleFriend = handleFriendsMap.get(friend.getUserId());
                if (Objects.nonNull(handleFriend)) {
                    friend.setWeight(friend.getWeight() + handleFriend.getWeight());
                    resultHandle.remove(handleFriend);
                }
            }
            recommendAll.addAll(resultSchool);
            recommendAll.addAll(resultHandle);
        }
        return recommendAll;
    }


    /**
     * 判断学校信息填写完整度
     */
    private int getSchoolInfoFillRatio(Long userId) {
        int result;
        Set<Long> users = Sets.newHashSet();
        users.add(userId);
        List<UserDataDTO> userDataDTOList = blendBaseUserCacheMapper.batchQueryUserBaseInfo(users.stream().collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(userDataDTOList)) {
            result = PROFILE_TYPE_0;
        } else {
            UserDataDTO userDataDTO = userDataDTOList.get(0);
            if (Objects.nonNull(userDataDTO.getSchoolId())) {
                result = PROFILE_TYPE_1;
            } else {
                result = PROFILE_TYPE_0;
            }
        }
        return result;
    }

    /**
     * 查询学校权重好友
     */
    private List<DegOneFrientWithWeight> querySchoolWeightFriends(Long userId, Long sequenceId, int degScore) {
        return blendBaseUserCacheMapper.querySchoolWeightFriends(userId, sequenceId, degScore);
    }

    /**
     * 查询操作推荐用户
     */
    private List<DegOneFrientWithWeight> queryHandleWeightFriends(Long userId, Long sequenceId, Long sequenceDegUp) {
        return blendBaseUserCacheMapper.queryHandleWeightFriends(userId, sequenceId, sequenceDegUp);
    }


    @Override
    public void initFriendV4(Long userId) {

    }
}
